package com.xzlf.netty;

import com.xzlf.Tank;
import com.xzlf.TankFrame;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class NettyServer {
    private static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    public static Map<UUID, Tank> tankServerMap = new HashMap<>();
    public static void main(String[] args) {
        EventLoopGroup boss = new NioEventLoopGroup(1);
        EventLoopGroup work = new NioEventLoopGroup(3);
        ServerBootstrap bootstrap = new ServerBootstrap();
        try {
            ChannelFuture future = bootstrap.group(boss, work)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new MsgDecoder());
                            pipeline.addLast(new MsgEncoder());
                            pipeline.addLast(new ServerHandler());
                        }
                    })
                    .bind(8888)
                    .sync();
            System.out.println("Server started!");
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }

    }

    static class ServerHandler extends SimpleChannelInboundHandler<Msg> {
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            clients.add(ctx.channel());
            if (TankFrame.INSTANCE.tankMap.size() != 0){
                TankFrame.INSTANCE.tankMap.values().forEach(tank -> {
                    clients.forEach(e -> e.writeAndFlush(new TankJoinMsg(tank)));
                });
            }
        }

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, Msg msg) throws Exception {
            clients.forEach(c -> c.writeAndFlush(msg));
        }
    }
}
